﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using Common;
using Opc.Ua;
using Opc.Ua.Client;
using OpcUaHelper;
using static System.Windows.Forms.VisualStyles.VisualStyleElement;

namespace Common.Opc
{


    /// <summary>
    /// OPCUA业务类
    /// </summary>
    public partial class OpcAct
    {

        public static string GlolbalVarTag { get; set; }
        object LockObj = new object();

        string GlobalVarId(string varName)
        {
            return $"{GlolbalVarTag}.{varName}";
        }
        public string TagStartFlag { get; set; } = "ns=4;";
        public bool ToSavePram()
        {
            return WriteSingleData(GlobalVarId("GVL_OPC.toPramSave"), true);
        }
        private OpcUaClient UaClient { get;  set; } = null;
        public Action<string, object> UpDataAction;//更新数据委托（TAG,值）
        public bool IsConnected
        {
            get
            {
                if (UaClient == null)
                {
                    return false;
                }
                return UaClient.Connected;
            }
        }
        private OpcAct()//构造方法传递URL
        {
            UaClient = new OpcUaClient();
        }

        public static OpcAct Instance { get; private set; } = new OpcAct();

        public bool Connect(string connString)
        {
            try
            {
                Task task1 = UaClient.ConnectServer(connString);
                task1.Wait(15000);
            }
            catch (Exception ex)
            {
                Log.Warn($"OPC 服务器连接异常:{ex.Message}");
            }
            if (UaClient.Connected)
            {
                return true;
            }
            else
            {
                return false;
            }
        }

        /// <summary>
        /// 读取关联节点
        /// </summary>
        /// <param name="PNode"></param>
        /// <returns></returns>
        public Dictionary<string, string> ReadCorrelationNode(string PNode)//
        {
            if (UaClient == null) return null;
            ReferenceDescription[] references = UaClient?.BrowseNodeReference(PNode);
            Dictionary<string, string> dicPlayNameNodeId = new Dictionary<string, string>();
            if (references != null)
            {
                foreach (var item in references)
                {
                    dicPlayNameNodeId.Add(item.DisplayName.ToString(), item.NodeId.ToString());
                }
            }
            return dicPlayNameNodeId;
        }
        public void DisConnect()
        {
            UaClient?.Disconnect();
        }

        public string TagCheck(string tag)
        {
            string tagUse = tag;
            if (!tagUse.StartsWith(TagStartFlag))
            {
                tagUse = GlobalVarId(tag);
            }
            return tagUse;
        }
        public void AddSubscription(string flag, string tag, Action<string, MonitoredItem, MonitoredItemNotificationEventArgs> callback)
        {
            if (!IsConnected) return;
            string tagUse = tag;
            if (!tagUse.StartsWith(TagStartFlag))
            {
                tagUse = GlobalVarId(tag);
            }
            UaClient.AddSubscription(flag, new string[] { tagUse }, callback);
        }

        public void AddSubscription(string flag, string[] tags, Action<string, MonitoredItem, MonitoredItemNotificationEventArgs> callback)
        {
            if (!IsConnected) return;
            if (tags==null||tags.Length==0)
            {
                return;
            }

            List<string> tagUseList = new List<string>();
            for (int i = 0; i < tags.Length; i++)
            {
                string tagUse = tags[i];
                if (!string.IsNullOrEmpty(tagUse))
                {
                    if (!tagUse.StartsWith(TagStartFlag))
                    {
                        tagUse = GlobalVarId(tagUse);
                    }
                    tagUseList.Add(tagUse);
                }
                
            }
          
            UaClient.AddSubscription(flag, tagUseList.ToArray(), callback);
        }

        public void RemoveSubscription(string key)
        {
            if (!IsConnected) return;
            UaClient.RemoveSubscription(key);
        }
        public T ReadSingleData<T>(string tag)
        {
            T t = default(T);
            try
            {
                if (!IsConnected)
                {
                    return t;
                }
                string tagUse = tag;
                if (!tag.StartsWith(TagStartFlag))
                {
                    tagUse = GlobalVarId(tag);
                }
                t = UaClient.ReadNode<T>(tagUse);
            }
            catch
            {

            }
            return t;
        }

        public bool WriteSingleData<T>(string tag, T value)
        {
            if (!IsConnected || !UaClient.Connected || tag == null) return false;
            string tagUse = tag;
            if (!tag.StartsWith(TagStartFlag))
            {
                tagUse = GlobalVarId(tag);
            }
            try
            {
                return UaClient.WriteNode<T>(tagUse, value);
            }
            catch (Exception)
            {

            }
            return false;
        }
        /// <summary>
        /// 异步数据写入
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <param name="tag"></param>
        /// <param name="value"></param>
        /// <returns></returns>
        public Task<bool> WriteSingleDataAsync<T>(string tag, T value)
        {
            if (!IsConnected || !UaClient.Connected || tag == null) return null;
            string tagUse = tag;
            if (!tag.StartsWith(TagStartFlag))
            {
                tagUse = GlobalVarId(tag);
            }
            try
            {
                return UaClient.WriteNodeAsync<T>(tagUse, value);
            }
            catch (Exception)
            {

            }
            return null;
        }
    }
}

